package com.kcht.rfid.rd30.secretary.dispatch.impl;

import com.kcht.rfid.rd30.secretary.core.command.*;
import com.kcht.rfid.rd30.secretary.core.common.ReaderCommandType;
import com.kcht.rfid.rd30.secretary.core.response.BasicResponse;
import com.kcht.rfid.rd30.secretary.core.response.ReaderResponse;
import com.kcht.rfid.rd30.secretary.dispatch.BaseCommandExecute;
import com.kcht.rfid.rd30.secretary.dispatch.IReaderChannel;
import com.kcht.rfid.rd30.secretary.dispatch.impl.operation.Invent;
import com.kcht.rfid.rd30.secretary.dispatch.impl.operation.Lock;
import com.kcht.rfid.rd30.secretary.dispatch.impl.operation.Read;
import com.kcht.rfid.rd30.secretary.dispatch.impl.operation.Write;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

/**
 * 使用的Rd30自定义接口
 */
@Slf4j
public class CustomCommandExecutor extends BaseCommandExecute implements Observer {

    /**
     * 循环执行线程
     */
    private CycleExecutor cycleThread;

    /**
     * 清点操作对象
     */
    private Invent invent = new Invent(this);
    /**
     * 读取操作对象
     */
    private Read read = new Read(this);
    /**
     * 写入操作对象
     */
    private Write write = new Write(this);
    /**
     * 上锁操作对象
     */
    private Lock lock = new Lock(this);

    /**
     * 响应列表
     */
    private List<BasicResponse> basicResponseList = new ArrayList<>();

    public CustomCommandExecutor(Map<String, String> params) {
        super(params);
    }

    /**
     * 执行管理
     */
    @Override
    protected void execute(IReaderChannel channel, ReaderCommand cmd, Observer[] observers) {
        this.interrupt();
        for (Observer observer : observers) {
            this.addObserver(observer);
        }
        if (cmd.getCommandType() == ReaderCommandType.SINGLE) {
            execute(channel, cmd.getBasicReaderCommands());
        } else {
            this.cycleThread = new CycleExecutor(channel,cmd.getBasicReaderCommands());
            this.cycleThread.start();
        }
    }


    /**
     * 具体执行指令
     */
    void execute(IReaderChannel channel, List<BasicReaderCommand> basicReaderCommands) {
        for (BasicReaderCommand basicReaderCommand : basicReaderCommands) {
            if (basicReaderCommand instanceof ReadCommand) {
                this.read.execute(channel, this.configuration, basicReaderCommand);
            } else if (basicReaderCommand instanceof WriteCommand) {
                this.write.execute(channel, this.configuration, basicReaderCommand);
            } else if (basicReaderCommand instanceof LockCommand) {
                this.lock.execute(channel, this.configuration, basicReaderCommand);
            } else if (basicReaderCommand instanceof InventoryCommand) {
                this.invent.execute(channel, this.configuration, basicReaderCommand);
            }
        }
        /*执行结果会调用本类的update方法*/
        clearUp(basicResponseList);
    }

    /**
     * 当this.read或this.lock或this.write工作完成时调用此方法，此方法被调用
     */
    @Override
    public void update(Observable o, Object arg) {
        this.basicResponseList.add((BasicResponse) arg);
    }

    /**
     * 整理数据,以一个标签为单位
     */
    private void clearUp(List<BasicResponse> basicResponseList) {
        Set<String> handledSet = new HashSet<>();
        Map<String, ReaderResponse> maps = new HashMap<>();
        for (BasicResponse basicResponse : basicResponseList) {
            String id = basicResponse.getEpc();
            if (!handledSet.contains(id)) {
                handledSet.add(id);
                ReaderResponse single = new ReaderResponse();
                single.setId(id);
                single.setIp(basicResponse.getIp());
                single.addReaderResponse(basicResponse);
                maps.put(id, single);
            } else {
                maps.get(id).addReaderResponse(basicResponse);
            }
        }
        for (String s : handledSet) {
            response(maps.get(s));
        }
        this.basicResponseList.clear();
    }

    /**
     * 循环清点线程关闭
     */
    @Override
    protected void interrupt() {
        if(this.cycleThread!=null){
            this.cycleThread.interruptCycle();
            this.cycleThread = null;
            this.deleteObservers();
        }
    }

    private void response(Object arg) {
        this.setChanged();
        this.notifyObservers(arg);
    }

    private class CycleExecutor extends Thread {
        /**
         * 中断循环执行线程
         */
        private volatile boolean interruptCycle = false;
        private IReaderChannel channel;
        private List<BasicReaderCommand> basicReaderCommands;

        public CycleExecutor(IReaderChannel channel, List<BasicReaderCommand> basicReaderCommands) {
            this.channel = channel;
            this.basicReaderCommands = basicReaderCommands;
        }

        @Override
        public void run() {
            while (true) {
                synchronized (this) {
                    if (!this.interruptCycle) {
                        CustomCommandExecutor.this.execute(this.channel, this.basicReaderCommands);
                    } else {
                        break;
                    }
                }
                /*延时5毫秒方便this.interruptCycle可以读取到内存值*/
                try {
                    Thread.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        public synchronized void interruptCycle(){
            this.interruptCycle = true;
        }
    }
}
